#include"Server.h"
#include"ServerUtil.h"
/*
* ����������
*/
void Server::openServer() {
    mysql_init(&mysql);
    if (mysql_real_connect(&mysql, "localhost", "root", "123", "qq", 0, NULL, 0) == NULL) {
        cout << "connect database fail\n";
    }
	fd = SocketHelper::open_listenfd(port);
    int c_fd;
    pthread_t pid;
    struct sockaddr_in clnt_adr;
    socklen_t clnt_adr_sz = sizeof(clnt_adr);
    while (1) {
        cout << "wait!" << endl;
        c_fd = accept(fd, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);
        if (c_fd < 0) {
            cout << "accept fail!" << endl;
            break;
        }
       //getnameinfo(addr, len, c_hostname, MAX, c_port, MAX, 0);
        cout << "fd:" << c_fd << endl;
        cout << "ip:" << inet_ntoa(clnt_adr.sin_addr) << endl;
        cout << "port:" << clnt_adr.sin_port << endl;
        int* cFdptr = new int(c_fd);
        pthread_create(&pid, NULL, openService, (void*)cFdptr);
    }
}
/*
* �����ͻ���
*/
void* Server::openService(void* arg) {
    pthread_detach(pthread_self());
    cout << "openService" << endl;
    int c_fd = *(int*)arg;
    size_t n;
    string qq,pwd,sql,sender,recevicer;
    pthread_t pid;
    int* result;
    Message message;
    unordered_map<string, int>::iterator it;
    while ((n = SocketHelper::rio_readn(c_fd, (char*)&message, sizeof(Message))) != 0) {
        cout << "read buf: " << n << endl;
        Message* m = new Message;
        *m = message;
        cout << "parseMessageType" << endl;
        switch (m->messageType) {
            case 0: //��¼��Ϣ
                cout << "login" << endl;
                m->messageType = c_fd;
                pthread_create(&pid, NULL, login, (void*)m);
                pthread_join(pid, (void**)&result);
                if (*result == 0) {//��¼ʧ��
                    return NULL;
                }
                delete result;
                break;
            case 1: //�˳���Ϣ
                cout << "exit" << endl;
                it = clientFds.find(m->sender);
                if (it != clientFds.end()) {
                    clientFds.erase(it);
                }
                close(c_fd);
                cout << "close client!" << endl;
                return NULL;
                break;
            case 2://˽����Ϣ
                cout << "private chat" << endl;
                pthread_create(&pid, NULL, privateChat, (void*)m);
                break;
            case 3://ע����Ϣ
                cout << "register" << endl;
                //1 . ����һ��qq
                qq = ServerUtil::createQQ(&mysql);
                cout << qq << endl;
                //2. ��qq������������ݿ�
                pwd = m->messageContent;
                sql = "insert into user values(0,'" + qq + "','" + pwd + "',now())";
                cout << sql << endl;
                if (mysql_query(&mysql, sql.c_str()) == 0) {
                    cout << "add sucessuful!!" << endl;
                };
                //3. ����
                strcpy(m->messageContent, qq.c_str());
                sendMessage(c_fd, *m);
                close(c_fd);
                //4. ����firendlist���ݿ�
                sql = "create table `friendlist_"+qq+"`(`friendQQ` varchar(4) not null, `chatContent` varchar(10000))";
                cout << sql << endl;
                if (mysql_query(&mysql, sql.c_str()) == 0) {
                    cout << "create sucessuful!!" << endl;
                }
                //5. ����addfriendlist���ݿ�
                sql = "create table addfrinedlist_" + qq + "(id int primary key auto_increment,friendId varchar(4),otherMessage varchar(100))";
                cout << sql << endl;
                if (mysql_query(&mysql, sql.c_str()) == 0) {
                    cout << "create addfrinedlist sucessuful!!" << endl;
                }
                return NULL;
                break;
            case 4://������ȡ������Ϣ
                strcpy(m->recevicer, std::to_string(c_fd).c_str()); //��c_fd��Ϣ�����message
                cout << "firend list" << endl;
                pthread_create(&pid, NULL, getFirend, (void*)m);
                break;
            case 5://�������Ӻ���
                cout << "add friend" << endl;
                m->messageType = c_fd;
                pthread_create(&pid, NULL, addFriend, (void*)m);
                break;
            case 6: //���ӽ����Ϣ
                cout << "add result" << endl;
                m->messageType = c_fd;
                pthread_create(&pid, NULL, addFriendResult, (void*)m);
                break;
            case 7://��ȡ��������Ϣ
                cout << "new friend" << endl;
                strcpy(m->recevicer, std::to_string(c_fd).c_str());
                pthread_create(&pid, NULL, newFriendMessage, (void*)m);
                break;
            default:
                cout << "unKnow Message!"<< endl;
        }
    }
    cout << "endService" << endl;
    return NULL;
}
/*
* ��ȡ��������Ϣ����
*/
void* Server::newFriendMessage(void* arg) {
    Message* m = (Message*)arg;
    string sender = m->sender;
    string sql;
    sql = "select friendId,otherMessage from addfrinedlist_" + sender.substr(0, 4);
    if (mysql_query(&mysql, sql.c_str()) == 0) {
        cout << "select ss\n";
        MYSQL_RES* result = mysql_store_result(&mysql);
        for (int i = 0; i < mysql_num_rows(result); i++) {
            MYSQL_ROW row = mysql_fetch_row(result);//��ȡ��һ������
            strcpy(m->f[i].firendId, row[0]);
            strcpy(m->f[i].chatContent, row[1]);
        }
    }
    //����
    sendMessage(atoi(m->recevicer), *m);
    delete m;
}
/*
* ���һ�����Ӻ��ѽ������
*/
void* Server::addFriendResult(void* arg) {
    Message* m = (Message*)arg;
    int c_fd = m->messageType;
    m->messageType = 6;
    string sender = m->sender, rec = m->recevicer;
    string sql;
    //������ݿ��е���������Ϣ
    sql = "delete from addfrinedlist_" + sender.substr(0, 4) + " where friendId = '" + rec.substr(0, 4) + "'";
    cout << sql << endl;
    if (mysql_query(&mysql, sql.c_str()) == 0) {
        cout << "delete ss\n";
    }
    if (m->messageContent[0] == 'T') {//�ɹ�
        //���ӵ����ݿ�
        string senderTableName = "friendlist_" + sender.substr(0, 4);
        string recTableName = "friendlist_" + rec.substr(0, 4);
        string sql = "insert into " + recTableName + " values('" + sender.substr(0, 4) + "','')"; 
        cout << sql << endl;
        if (mysql_query(&mysql, sql.c_str()) == 0) {
            cout << "add friend ss\n";
        }
        sql = "insert into " + senderTableName + " values('" + rec.substr(0, 4) + "','')";
        cout << sql << endl;
        if (mysql_query(&mysql, sql.c_str()) == 0) {
            cout << "add friend ss\n";
        }
        //֪ͨ
        //֪ͨ����
        auto it = clientFds.find(rec.substr(0,4));
        if (it == clientFds.end()) {
            cout << "target not online��" << endl;
        }
        else {
            cout << "target online��" << endl;
            sendMessage(it->second, *m);
        }
        //֪ͨ������
        strcpy(m->sender, m->recevicer);
        sendMessage(c_fd, *m);

    }
    else { //ʧ��
        cout << "add friend ff" << endl;
    } 
    delete m;
}
/*
* ���һ�����Ӻ��ѷ���
*/
void* Server::addFriend(void* arg) {
    Message* m = (Message*)arg;
    int c_fd = m->messageType;
    m->messageType = 5;
    //��ѯ���ݿ����޸��û�
    string recevicer = m->recevicer,sender = m->sender;
    string sql = "select * from user where qq = '" + recevicer.substr(0,4) + "'";
    cout << sql << endl;
    if (mysql_query(&mysql, sql.c_str()) == 0) {
        cout << "mysql_query ss\n";
        if (mysql_num_rows(mysql_store_result(&mysql)) == 0) {//������
            strcpy(m->messageContent, "F");
            cout << "friend not exist!!!" << endl;
            sendMessage(c_fd, *m);
        }
        else {  //����
            cout << "friend exist!!!" << endl;
            //���ӵ����ݿ�
            sql = "insert into addfrinedlist_" + recevicer.substr(0, 4) + " values(0, '" + sender.substr(0, 4) + "', '" + m->messageContent + "')";
            cout << sql << endl;
            if (mysql_query(&mysql, sql.c_str()) == 0) {
                cout << "insert into addfrinedlist sucessuful!!" << endl;
            }
            //���͸����շ�
            auto it = clientFds.find(recevicer.substr(0, 4));
            if (it == clientFds.end()) {
                cout << "add ffff  target not online!" << endl;
            }
            else {
                cout << "add ffff target online!" << endl;
                sendMessage(it->second, *m);
            }
            //���͸����ͷ�
            strcpy(m->messageContent, "S");
            sendMessage(c_fd, *m);
        }
    }
    delete m;
}
/*
* ��ɵ�¼����
*/
void* Server::login(void* arg) {
    Message* m = (Message*)arg;
    int c_fd = m->messageType;
    m->messageType = 0;
    int* result = new int(1);
    string qq = m->sender, pwd = m->messageContent;
    string sql = "select * from user where qq = '" + qq + "' and pwd = '" + pwd+"'";
    cout << sql << endl;
    //��ѯ���ݿ�����ƥ���
    if (mysql_query(&mysql,sql.c_str()) != 0) {
        cout << "mysql_query fail\n";
    }
    if (mysql_num_rows(mysql_store_result(&mysql)) == 0) {//��¼ʧ��
        *result = 0;
        cout << "login ff!" << endl;
        sendMessage(c_fd, *m);
        close(c_fd);
        return NULL;
    }
    else {
        cout << "login ss!" << endl;
        strcpy(m->messageContent, "T");
        clientFds.insert(pair<string, int>(m->sender, c_fd));
        sendMessage(c_fd, *m);
    }
    delete m;
    return result;
}
/*
* ��ɻ�ȡ������Ϣ����
*/
void* Server::getFirend(void* arg) {
    Message* m = (Message*)arg;
    //1. ��ѯ
    string qq = m->sender;
    string sql = "select * from friendlist_" + qq.substr(0,4);
    cout << sql << endl;
    if (mysql_query(&mysql, sql.c_str()) == 0) {
        cout << "select s!" << endl;
        MYSQL_RES* result = mysql_store_result(&mysql);
        for (int i = 0; i < mysql_num_rows(result); i++) {
            Firend f;
            MYSQL_ROW row = mysql_fetch_row(result);//��ȡ��һ������
            strcpy(f.firendId, row[0]);
            strcpy(f.chatContent, row[1]);
            m->f[i] = f;
        }
    }
    //2. ����
    sendMessage(atoi(m->recevicer), *m);
    delete m;
}
/*
* ���˽�ķ���
*/
void* Server::privateChat(void* arg) {
    string charContent;
    Message* m = (Message*)arg;
    //1.�ҵ�Ŀ��socket
    string rev = m->recevicer;
    auto it = clientFds.find(rev.substr(0,4));
    if (it == clientFds.end()) {
        cout << "target not online" << endl;
    }
    //2.���ӵ����ݿ�  ����2��
    //��1����ȡ�����ļ�¼
    string sender = m->sender, rec = m->recevicer;
    string senderTableName = "friendlist_" + sender.substr(0, 4);
    string recTableName = "friendlist_" + rec.substr(0, 4);
    string sql = "select chatContent from " + senderTableName + " where friendQQ = " + rec.substr(0, 4);
    cout << sql << endl;
    if (mysql_query(&mysql, sql.c_str()) == 0) {
        cout << "select ssss!" << endl;
        MYSQL_RES* result = mysql_store_result(&mysql);//��ȡ���
        for (int i = 0; i < mysql_num_rows(result); i++) {
            MYSQL_ROW row = mysql_fetch_row(result);//��ȡ��һ������
            charContent = row[0];
        }
    }
    // (2) ׷��
    string nowTime = ServerUtil::getNowTime();
    //charContent = charContent + "\n" + nowTime + "\n[" +m->sender+"]" + m->messageContent;
    // (3) ׷�ӵ����ݿ�
    sql = "update " + senderTableName + " set chatContent = " + "concat('" + charContent + "',CHAR(10),'" + nowTime + "',CHAR(10),'[" + sender.substr(0,4) + "]','" + (m->messageContent+10) + "') WHERE friendQQ = " + rec.substr(0, 4);
    cout << sql << endl;
    if (mysql_query(&mysql, sql.c_str()) == 0) {
        cout << "update ssss!" << endl;
    }
    sql = "update " + recTableName + " set chatContent = " + "concat('" + charContent + "',CHAR(10),'" + nowTime + "',CHAR(10),'[" + sender.substr(0, 4) + "]','" + (m->messageContent + 10) + "') WHERE friendQQ = " + sender.substr(0, 4);
    cout << sql << endl;
    if (mysql_query(&mysql, sql.c_str()) == 0) {
        cout << "update ssss!" << endl;
    }
    //2.������Ϣ
    sql = "select chatContent from " + senderTableName + " where friendQQ = " + rec.substr(0, 4);
    cout << sql << endl;
    if (mysql_query(&mysql, sql.c_str()) == 0) {
        cout << "select ssss!" << endl;
        MYSQL_RES* result = mysql_store_result(&mysql);//��ȡ���
        for (int i = 0; i < mysql_num_rows(result); i++) {
            MYSQL_ROW row = mysql_fetch_row(result);//��ȡ��һ������
            charContent = row[0];
        }
    }
    strcpy(m->f[0].chatContent, charContent.c_str());
    if (it == clientFds.end()) {
        cout << "target not online!!" << endl;
    }
    else {
        sendMessage(it->second, *m);
    }
    //3.����
    delete m;
}
/*
* ���һ����Ϣ����
*/
void Server::sendMessage(int clientFd, Message m) {
    cout << "sendMessage" << endl;
    int n = write(clientFd, (void*)&m, sizeof(Message));
    cout << n << endl;
    cout << "end" << endl;
}